import csv
import json
import os
from typing import Iterable, Any

import yaml
from openpyxl import load_workbook


class ReadFileData(object):

    def __init__(self, path, **kwargs):
        if not os.path.exists(path):
            return
        self.path = path
        self.data = None
        self.extra_param = kwargs
        self.parse_file()

    def parse_file(self):
        if self.path.endswith(".xls") or self.path.endswith(".xlsx"):
            self.excel_parser()
        elif self.path.endswith(".csv"):
            self.csv_parser()
        elif self.path.endswith(".yaml"):
            self.yaml_parser()
        elif self.path.endswith(".json"):
            self.json_loader()

    def __excel_parser(self) -> list:
        work_book = load_workbook(filename=self.path)
        sheet_names = work_book.sheetnames
        key = self.extra_param.get('key')
        line = self.extra_param.get("line")
        sheet = self.extra_param.get("sheet")
        datas = list()
        if sheet:
            if sheet in sheet_names:
                expect_sheet = work_book[sheet]
                for row in expect_sheet.rows:
                    datas.append(tuple(cell.value for cell in row))
                if line:
                    if isinstance(line, int):
                        if line <= len(datas):
                            datas = datas[line - 1]
                    elif isinstance(line, tuple) or isinstance(line, list):
                        if len(line) == 2 and line[0] <= len(datas) and len(datas) >= line[1] > line[0] and (
                                type(line[0]) is int and type(line[1]) is int):
                            datas = datas[line[0]:line[1]]
        else:
            for sheet in sheet_names:
                per_sheet = work_book[sheet]
                for row in per_sheet.rows:
                    per_data = tuple(cell.value for cell in row)
                    datas.append(per_data)
        return datas

    def __csv_parser(self) -> list:
        line = self.extra_param.get('line')
        datas = []
        with open(self.path)as f:
            f_csv = csv.reader(f)
            for row in f_csv:
                datas.append(tuple(row))
        if line:
            if isinstance(line, int):
                if line <= len(datas):
                    datas = datas[line]
            elif isinstance(line, tuple) or isinstance(line, list):
                if len(line) == 2 and line[0] <= len(datas) and len(datas) >= line[1] > line[0] and (
                        type(line[0]) is int and type(line[1]) is int):
                    datas = datas[line[0]:line[1]]
        return datas

    def __yaml_parser(self) -> dict:
        key = self.extra_param.get("key")
        all_datas = dict()
        with open(self.path) as f:
            datas = f.read()
        all_datas = yaml.load(datas, Loader=yaml.FullLoader)
        if key:
            all_datas = all_datas.get(key) if all_datas.get(key) else all_datas
        return all_datas

    def __json_loader(self) -> Any:
        key = self.extra_param.get('key')
        with open(self.path, 'rb') as f:
            datas = f.read()
        try:
            datas = json.loads(datas)
        except Exception:
            pass
        if isinstance(datas, Iterable):
            if isinstance(datas, dict):
                datas = datas.get(key) if datas.get(key) else datas
            return datas

        else:
            return list()

    def excel_parser(self):
        self.data = self.__excel_parser()

    def csv_parser(self):
        self.data = self.__csv_parser()

    def yaml_parser(self):
        self.data = self.__yaml_parser()

    def json_loader(self):
        self.data = self.__json_loader()